﻿//运算符可以经过重载实现更自然的自定义类型语法。运算符重载非常适合用来表示最普通的基本数据类型的自定义结构体。
//例如，自定义数学类型很适合实现运算符重载。

//下面的符号运算符都是可以重载的：
// +(一元的)    -（一元的）  !   ~   ++
// --            +           -   *   /
// %             &           |   ^   <<
// >>            ==          !=  >   <
// >=           <=

//下面的运算符也可以重载：
//    隐式和显式转换（使用implicit和explicit关键字）
//    常量true和false

//下面的运算符可以间接进行重载：
//    复合赋值运算符（例如+=、/=）可以通过重载非复合运算符（例如+、-）进行隐式重载。
//    条件运算符&&和||可以通过重载位运算符&和|进行隐式重载。
using System;
//4.8.1 运算符函数
//运算符是通过声明一个运算符函数进行重载的。运算符函数具有以下规则：
//    函数名是通过operator关键字及其后的运算符指定的
//    运算符函数必须标记为static和public
//    运算符函数的参数表示的是操作数
//    运算符函数的返回类型表示的是表达式的结果
//    运算符函数所声明的类型至少有一个操作数

namespace _122_运算符重载
{
    //在下面的例子中，我们定义了一个名为Note的结构体，它表示一个音符，然后再重载运算符+：
    public struct Note
    {
        int value;
        public Note(int semitonesFromA) { value = semitonesFromA; }
        public static Note operator +(Note x, int semitones)
        {
            return new Note(x.value + semitones);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //这个重载使我们能够给一个Note加上一个int：
            Note B = new Note(2);
            Note CSharp = B + 2;
            //重载一个赋值运算符会自动支持相应的复合赋值运算符。在上例中，因为我们重载了+号，所以也就能够使用+=了：
            CSharp += 2;

            Console.ReadKey();
        }
    }
}
//4.8.2 重载等号和比较运算符
//有些时候，我们在编写结构体或类时会需要重载等号和比较运算符。重载等号和比较运算符有一些特殊的规则和要求，这些规则可以总结如下：
// 成对重载
//    C#编译器要求逻辑上成对的运算符必须同时定义。这些运算符包括（== !=）、（< >）和（<= =>）。
// Equals和GetHashCode
//    在大多数情况中，如果重载了（==）和（!=），那么通常也需要重载对象中定义的Equals和GetHashCode方法使之具有合理的行为。如果没有按要求重载，那么C#编译器将会发出警告。
// IComparable和IComparable<T>
//    如果重载了（< >）和（<= =>），那么还应该实现IComparable和IComparable<T>。